<template>
  <div class="container">
    <Menu></Menu>
    <div class="box">
      <video ref="localVideo" autoplay muted></video>
      <video ref="remoteVideo" autoplay></video>
    </div>
  </div>
</template>

<script setup lang="ts">
import 'https://cdn.scaledrone.com/scaledrone.min.js';

import { ref } from 'vue';

if (!location.hash) {
  location.hash = Math.floor(Math.random() * 0xffffff).toString(16);
}
const roomHash = location.hash.substring(1);
const localVideo = ref(null);
const remoteVideo = ref(null);

const drone = new ScaleDrone('zmOBbhiKVvRpCQoY');
const roomName = `observable-${roomHash}`;
const configuration = {
  iceServers: [
    {
      urls: 'stun:stun.l.google.com:19302',
    },
  ],
};
let room;
let pc;

function onSuccess() {}
function onError(error) {
  console.error(error);
}

drone.on('open', (error) => {
  if (error) {
    return console.error(error);
  }
  room = drone.subscribe(roomName);
  room.on('open', (error) => {
    if (error) {
      onError(error);
    }
  });
  room.on('members', (members) => {
    console.log('MEMBERS', members);
    const isOfferer = members.length >= 2;
    startWebRTC(isOfferer);
  });
});

function sendMessage(message) {
  drone.publish({
    room: roomName,
    message,
  });
}

function startWebRTC(isOfferer) {
  pc = new RTCPeerConnection(configuration);

  pc.onicecandidate = (event) => {
    if (event.candidate) {
      sendMessage({ candidate: event.candidate });
    }
  };

  if (isOfferer) {
    pc.onnegotiationneeded = () => {
      pc.createOffer().then(localDescCreated).catch(onError);
    };
  }

  pc.ontrack = (event) => {
    const stream = event.streams[0];
    if (!remoteVideo.value.srcObject || remoteVideo.value.srcObject.id !== stream.id) {
      remoteVideo.value.srcObject = stream;
    }
  };

  navigator.mediaDevices
    .getUserMedia({
      audio: true,
      video: true,
    })
    .then((stream) => {
      localVideo.value.srcObject = stream;
      stream.getTracks().forEach((track) => pc.addTrack(track, stream));
    }, onError);

  room.on('data', (message, client) => {
    if (client.id === drone.clientId) {
      return;
    }

    if (message.sdp) {
      pc.setRemoteDescription(
        new RTCSessionDescription(message.sdp),
        () => {
          if (pc.remoteDescription.type === 'offer') {
            pc.createAnswer().then(localDescCreated).catch(onError);
          }
        },
        onError,
      );
    } else if (message.candidate) {
      pc.addIceCandidate(new RTCIceCandidate(message.candidate), onSuccess, onError);
    }
  });
}

function localDescCreated(desc) {
  pc.setLocalDescription(desc, () => sendMessage({ sdp: pc.localDescription }), onError);
}
</script>

<style scoped>
@import './index.less';
</style>
